home *** CD-ROM | disk | FTP | other *** search
/ Linux Cubed Series 7: Sunsite / Linux Cubed Series 7 - Sunsite Vol 1.iso / system / news / inn1.000 / inn1.4sec-linux-src.tar / inn / lib / inndcomm.c < prev    next >
C/C++ Source or Header  |  1993-03-18  |  7KB  |  379 lines

  1. /*  $Revision: 1.18 $
  2. **
  3. **  Library routines to let other programs control innd.
  4. */
  5. #include "configdata.h"
  6. #include <stdio.h>
  7. #include <ctype.h>
  8. #include <errno.h>
  9. #include <sys/types.h>
  10. #include <sys/stat.h>
  11. #include <fcntl.h>
  12. #if    defined(DO_NEED_TIME)
  13. #include <time.h>
  14. #endif    /* defined(DO_NEED_TIME) */
  15. #include <sys/time.h>
  16. #include <sys/socket.h>
  17. #if    defined(DO_HAVE_UNIX_DOMAIN)
  18. #include <sys/un.h>
  19. #endif    /* defined(DO_HAVE_UNIX_DOMAIN) */
  20. #include "nntp.h"
  21. #include "paths.h"
  22. #include "libinn.h"
  23. #include "clibrary.h"
  24. #include "inndcomm.h"
  25. #include "macros.h"
  26.  
  27. #define MIN_BUFFER_SIZE        4096
  28.  
  29. STATIC char            ICCsockname[sizeof _PATH_TEMPSOCK];
  30. #if    defined(DO_HAVE_UNIX_DOMAIN)
  31. STATIC struct sockaddr_un    ICCserv;
  32. STATIC struct sockaddr_un    ICCclient;
  33. #endif    /* defined(DO_HAVE_UNIX_DOMAIN) */
  34. STATIC int            ICCfd;
  35. STATIC int            ICCtimeout;
  36. char                *ICCfailure;
  37.  
  38.  
  39. /*
  40. **  Set the timeout.
  41. */
  42. void
  43. ICCsettimeout(i)
  44.     int        i;
  45. {
  46.     ICCtimeout = i;
  47. }
  48.  
  49.  
  50. /*
  51. **  Get ready to talk to the server.
  52. */
  53. int
  54. ICCopen()
  55. {
  56.     int        mask;
  57.     int        oerrno;
  58.  
  59.     /* Create a temporary name. */
  60.     (void)strcpy(ICCsockname, _PATH_TEMPSOCK);
  61.     (void)mktemp(ICCsockname);
  62.     if (unlink(ICCsockname) < 0 && errno != ENOENT) {
  63.     ICCfailure = "unlink";
  64.     return -1;
  65.     }
  66.  
  67. #if    defined(DO_HAVE_UNIX_DOMAIN)
  68.     /* Make a socket and give it the name. */
  69.     if ((ICCfd = socket(AF_UNIX, SOCK_DGRAM, 0)) < 0) {
  70.     ICCfailure = "socket";
  71.     return -1;
  72.     }
  73.     (void)memset((POINTER)&ICCclient, 0, sizeof ICCclient);
  74.     ICCclient.sun_family = AF_UNIX;
  75.     (void)strcpy(ICCclient.sun_path, ICCsockname);
  76.     mask = umask(0);
  77.     if (bind(ICCfd, (struct sockaddr *)&ICCclient,
  78.         AF_UNIX_SOCKSIZE(ICCclient)) < 0) {
  79.     oerrno = errno;
  80.     (void)umask(mask);
  81.     errno = oerrno;
  82.     ICCfailure = "bind";
  83.     return -1;
  84.     }
  85.     (void)umask(mask);
  86.  
  87.     /* Name the server's socket. */
  88.     (void)memset((POINTER)&ICCserv, 0, sizeof ICCserv);
  89.     ICCserv.sun_family = AF_UNIX;
  90.     (void)strcpy(ICCserv.sun_path, _PATH_NEWSCONTROL);
  91. #else
  92.     /* Make a named pipe and open it. */
  93.     mask = umask(0);
  94.     if (mkfifo(ICCsockname, 0666) < 0) {
  95.     oerrno = errno;
  96.     (void)umask(mask);
  97.     errno = oerrno;
  98.     ICCfailure = "mkfifo";
  99.     return -1;
  100.     }
  101.     (void)umask(mask);
  102.     if ((ICCfd = open(ICCsockname, O_RDWR)) < 0) {
  103.     ICCfailure = "open";
  104.     return -1;
  105.     }
  106. #endif    /* defined(DO_HAVE_UNIX_DOMAIN) */
  107.  
  108.     ICCfailure = NULL;
  109.     return 0;
  110. }
  111.  
  112.  
  113. /*
  114. **  Close down.
  115. */
  116. int
  117. ICCclose()
  118. {
  119.     int        i;
  120.  
  121.     ICCfailure = NULL;
  122.     i = 0;
  123.     if (close(ICCfd) < 0) {
  124.     ICCfailure = "close";
  125.     i = -1;
  126.     }
  127.     if (unlink(ICCsockname) < 0 && errno != ENOENT) {
  128.     ICCfailure = "unlink";
  129.     i = -1;
  130.     }
  131.     return i;
  132. }
  133.  
  134.  
  135. /*
  136. **  Get the server's pid.
  137. */
  138. STATIC PID_T
  139. ICCserverpid()
  140. {
  141.     PID_T        pid;
  142.     FILE        *F;
  143.     char        buff[SMBUF];
  144.  
  145.     pid = 1;
  146.     if ((F = fopen(_PATH_SERVERPID, "r")) != NULL) {
  147.     if (fgets(buff, sizeof buff, F) != NULL)
  148.         pid = atoi(buff);
  149.     (void)fclose(F);
  150.     }
  151.     return pid;
  152. }
  153.  
  154.  
  155. /*
  156. **  See if the server is still there.  When in doubt, assume yes.
  157. **  Cache the pid since a rebooted server won't know about our pending
  158. **  message.
  159. */
  160. STATIC BOOL
  161. ICCserveralive(pid)
  162.     PID_T        pid;
  163. {
  164.     if (kill(pid, 0) > 0 || errno != ESRCH)
  165.     return TRUE;
  166.     return FALSE;
  167. }
  168.  
  169.  
  170. /*
  171. **  Send an arbitrary command to the server.
  172. */
  173. int
  174. ICCcommand(cmd, argv, replyp)
  175.     char        cmd;
  176.     char        *argv[];
  177.     char        **replyp;
  178. {
  179.     char        *buff;
  180.     char        *p;
  181.     char        *q;
  182.     char        save;
  183.     int            bufsiz;
  184.     int            i;
  185. #if    !defined(DO_HAVE_UNIX_DOMAIN)
  186.     int            fd;
  187. #endif    /* !defined(DO_HAVE_UNIX_DOMAIN) */
  188.     int            len;
  189.     FDSET        Rmask;
  190.     struct timeval    T;
  191.     PID_T        pid;
  192.  
  193.     /* Is server there? */
  194.     pid = ICCserverpid();
  195.     if (!ICCserveralive(pid)) {
  196.     ICCfailure = "dead server";
  197.     return -1;
  198.     }
  199.  
  200.     /* Get the length of the buffer. */
  201.     bufsiz = strlen(ICCsockname) + 1 + 1;
  202.     for (i = 0; (p = argv[i]) != NULL; i++)
  203.     bufsiz += 1 + strlen(p);
  204.     if (bufsiz < MIN_BUFFER_SIZE)
  205.     bufsiz = MIN_BUFFER_SIZE;
  206.     buff = malloc((unsigned int)bufsiz);
  207.     if (buff == NULL) {
  208.     ICCfailure = "malloc";
  209.     return -1;
  210.     }
  211.     if (replyp)
  212.     *replyp = NULL;
  213.  
  214.     /* Format the message. */
  215.     (void)sprintf(buff, "%s%c%c", ICCsockname, SC_SEP, cmd);
  216.     for (p = buff + strlen(buff), i = 0; (q = argv[i]) != NULL; i++) {
  217.     *p++ = SC_SEP;
  218.     p += strlen(strcpy(p, q));
  219.     }
  220.  
  221.     /* Send message. */
  222.     ICCfailure = NULL;
  223.     len = p - buff;
  224. #if    defined(DO_HAVE_UNIX_DOMAIN)
  225.     if (sendto(ICCfd, buff, len, 0,
  226.         (struct sockaddr *)&ICCserv, AF_UNIX_SOCKSIZE(ICCserv)) < 0) {
  227.     DISPOSE(buff);
  228.     ICCfailure = "sendto";
  229.     return -1;
  230.     }
  231. #else
  232.     if ((fd = open(_PATH_NEWSCONTROL, O_WRONLY)) < 0) {
  233.     DISPOSE(buff);
  234.     ICCfailure = "open";
  235.     return -1;
  236.     }
  237.     if (write(fd, buff, len) != len) {
  238.     i = errno;
  239.     DISPOSE(buff);
  240.     (void)close(fd);
  241.     errno = i;
  242.     ICCfailure = "write";
  243.     return -1;
  244.     }
  245.     (void)close(fd);
  246. #endif    /* defined(DO_HAVE_UNIX_DOMAIN) */
  247.  
  248.     /* Possibly get a reply. */
  249.     switch (cmd) {
  250.     default:
  251.     if (ICCtimeout >= 0)
  252.         break;
  253.     /* FALLTHROUGH */
  254.     case SC_SHUTDOWN:
  255.     case SC_XABORT:
  256.     case SC_XEXEC:
  257.     DISPOSE(buff);
  258.     return 0;
  259.     }
  260.  
  261.     /* Wait for the reply. */
  262.     for ( ; ; ) {
  263.     FD_ZERO(&Rmask);
  264.     FD_SET(ICCfd, &Rmask);
  265.     T.tv_sec = ICCtimeout ? ICCtimeout : 120;
  266.     T.tv_usec = 0;
  267.     i = select(ICCfd + 1, &Rmask, (FDSET *)NULL, (FDSET *)NULL, &T);
  268.     if (i < 0) {
  269.         DISPOSE(buff);
  270.         ICCfailure = "select";
  271.         return -1;
  272.     }
  273.     if (i > 0 && FD_ISSET(ICCfd, &Rmask))
  274.         /* Server reply is there; go handle it. */
  275.         break;
  276.  
  277.     /* No data -- if we timed out, return. */
  278.     if (ICCtimeout) {
  279.         DISPOSE(buff);
  280.         errno = ETIMEDOUT;
  281.         ICCfailure = "timeout";
  282.         return -1;
  283.     }
  284.  
  285.     if (!ICCserveralive(pid)) {
  286.         DISPOSE(buff);
  287.         ICCfailure = "dead server";
  288.         return -1;
  289.     }
  290.     }
  291.  
  292.     /* Read the reply. */
  293.     i = RECVorREAD(ICCfd, buff, bufsiz - 1);
  294.     if (i < 0) {
  295.     DISPOSE(buff);
  296.     ICCfailure = "read";
  297.     return -1;
  298.     }
  299.     buff[i] = '\0';
  300.  
  301.     /* Parse the reply; expected to be like "<exitcode><space><text>" */
  302.     i = 0;
  303.     if (CTYPE(isdigit, buff[0])) {
  304.     for (p = buff; *p && CTYPE(isdigit, *p); p++)
  305.         continue;
  306.     if (*p) {
  307.         save = *p;
  308.         *p = '\0';
  309.         i = atoi(buff);
  310.         *p = save;
  311.     }
  312.     }
  313.     if (replyp)
  314.     *replyp = buff;
  315.     else
  316.     DISPOSE(buff);
  317.     return i;
  318. }
  319.  
  320.  
  321. /*
  322. **  Send a "cancel" command.
  323. */
  324. int
  325. ICCcancel(msgid)
  326.     char    *msgid;
  327. {
  328.     char    *args[2];
  329.  
  330.     args[0] = msgid;
  331.     args[1] = NULL;
  332.     return ICCcommand(SC_CANCEL, args, (char **)NULL);
  333. }
  334.  
  335.  
  336. /*
  337. **  Send a "go" command.
  338. */
  339. int
  340. ICCgo(why)
  341.     char    *why;
  342. {
  343.     char    *args[2];
  344.  
  345.     args[0] = why;
  346.     args[1] = NULL;
  347.     return ICCcommand(SC_GO, args, (char **)NULL);
  348. }
  349.  
  350.  
  351. /*
  352. **  Send a "pause" command.
  353. */
  354. int
  355. ICCpause(why)
  356.     char    *why;
  357. {
  358.     char    *args[2];
  359.  
  360.     args[0] = why;
  361.     args[1] = NULL;
  362.     return ICCcommand(SC_PAUSE, args, (char **)NULL);
  363. }
  364.  
  365.  
  366. /*
  367. **  Send a "reserve" command.
  368. */
  369. int
  370. ICCreserve(why)
  371.     char    *why;
  372. {
  373.     char    *args[2];
  374.  
  375.     args[0] = why;
  376.     args[1] = NULL;
  377.     return ICCcommand(SC_RESERVE, args, (char **)NULL);
  378. }
  379.